#include "Point.h"



///<************************************************************************************************************>
///<************************************* region CONSTANTS DEFINITION ******************************************>
///<************************************************************************************************************>

const CICore::Point CICore::Point::ORIGIN = Point (0, 0, 0);
/***************************************************************************************************************
************************************** endregion CONSTANTS DEFINITION ******************************************
****************************************************************************************************************/







/// <summary>
/// Constructor
/// </summary>
/// <param name="px"> The x-axis value </param>
/// <param name="py"> The y-axis value </param>
/// <param name="pz"> The z-axis value </param>
CICore::Point::Point (const float px, const float py, const float pz) {
    x = px;
    y = py;
    z = pz;
}

/// <summary>
/// Constructor
/// </summary>
/// <param name="v"> The vertex from which retrieve information </param>
CICore::Point::Point (const Vertex& v) {
    x = v.x;
    y = v.y;
    z = v.z;
}

/// <summary>
/// Destructor
/// </summary>
CICore::Point::~Point() {}








///<************************************************************************************************************>
///<**************************************** region Utility Methods ********************************************>
///<************************************************************************************************************>

void CICore::Point::Transform (const CICore::Matrix &m) {
    Point p;

    //Computing the transformation
    p.x = x * m.elements[ 0 ] + y * m.elements[ 4 ] + z * m.elements[ 8 ] + m.elements[ 12 ];
    p.y = x * m.elements[ 1 ] + y * m.elements[ 5 ] + z * m.elements[ 9 ] + m.elements[ 13 ];
    p.z = x * m.elements[ 2 ] + y * m.elements[ 6 ] + z * m.elements[ 10 ] + m.elements[ 14 ];    

    //Setting the new vertex's coordinates
    x = p.x;
    y = p.y;
    z = p.z;
}
/***************************************************************************************************************
******************************************* endregion Utility Methods ******************************************
****************************************************************************************************************/













///<************************************************************************************************************>
///<******************************* region BASIC POINT's UNARY OPERATIONS *************************************>
///<************************************************************************************************************>

/// <summary>
/// Postfix increment
/// </summary>
/// <param name="p"> The point to be modified </param>
/// <returns> A reference of the point modified </returns>
CICore::Point& CICore::operator ++ (Point& p, int) {
    p.x++;
    p.y++;
    p.z++;

    return p;
}

/// <summary>
/// Prefix increment
/// </summary>
/// <param name="p"> The point to be modified </param>
/// <returns> A reference of the point modified </returns>
CICore::Point& CICore::operator ++ (Point& p) {
    ++(p.x);
    ++(p.y);
    ++(p.z);

    return p;
}

/// <summary>
/// Postfix decrement
/// </summary>
/// <param name="p"> The point to be modified </param>
/// <returns> A reference of the point modified </returns>
CICore::Point& CICore::operator -- (Point& p, int) {
    p.x--;
    p.y--;
    p.z--;

    return p;
}

/// <summary>
/// Prefix decrement
/// </summary>
/// <param name="p"> The point to be modified </param>
/// <returns> A reference of the point modified </returns>
CICore::Point& CICore::operator -- (Point& p) {
    --(p.x);
    --(p.y);
    --(p.z);

    return p;
}

/// <summary>
/// Basic Assignment
/// </summary>
/// <param name="v"> The vertex from which retrieve information </param>
/// <returns> A reference of the point modified </returns>
CICore::Point& CICore::Point::operator = (Vertex& v) {
    x = v.x;
    y = v.y;
    z = v.z;

    return (*this);
}
/***************************************************************************************************************
********************************** endregion BASIC POINT's UNARY OPERATIONS ***********************************
****************************************************************************************************************/









///<************************************************************************************************************>
///<******************************* region BASIC POINT's BINARY OPERATIONS ************************************>
///<************************************************************************************************************>

/// <summary>
/// Sum between two points
/// </summary>
/// <param name="a"> The first point </param>
/// <param name="b"> The second point </param>
/// <returns> The sum between the two points </returns>
CICore::Point CICore::operator + (const Point& a, const Point& b) {
    return Point(a.x+b.x, a.y+b.y, a.z+b.z);
}

/// <summary>
/// Assignment by addition between two points
/// </summary>
/// <param name="a"> The point to be modified </param>
/// <param name="b"> The point to be added </param>
/// <returns> A reference of the point modified </returns>
CICore::Point& CICore::operator += (Point& a, const Point& b) {
    a.x += b.x;
    a.y += b.y;
    a.z += b.z;

    return a;
}

/// <summary>
/// Difference between two points
/// </summary>
/// <param name="a"> The first point </param>
/// <param name="b"> The second point </param>
/// <returns> The difference between the two points </returns>
CICore::Point CICore::operator - (const Point& a, const Point& b) {
    return Point(a.x-b.x, a.y-b.y, a.z-b.z);
}

/// <summary>
/// Assignment by substraction between two points
/// </summary>
/// <param name="a"> The point to be modified </param>
/// <param name="b"> The point to be substracted </param>
/// <returns> A reference of the point modified </returns>
CICore::Point& CICore::operator -= (Point& a, const Point& b) {
    a.x -= b.x;
    a.y -= b.y;
    a.z -= b.z;

    return a;
}

/// <summary>
/// Product between two points
/// </summary>
/// <param name="a"> The multiplicand point </param>
/// <param name="b"> The multiplier point </param>
/// <returns> The product between the two points </returns>
CICore::Point CICore::operator * (const Point& a, const Point& b) {
    return Point(a.x*b.x, a.y*b.y, a.z*b.z);
}

/// <summary>
/// Assignment by multiplication between two points
/// </summary>
/// <param name="a"> The point to be modified </param>
/// <param name="b"> The multiplier point </param>
/// <returns> A reference of the point modified </returns>
CICore::Point& CICore::operator *= (Point& a, const Point& b) {
    a.x *= b.x;
    a.y *= b.y;
    a.z *= b.z;

    return a;
}

/// <summary>
/// Quotient between two points
/// </summary>
/// <param name="a"> The dividend point </param>
/// <param name="b"> The divisor point </param>
/// <returns> The quotient between the two points </returns>
CICore::Point CICore::operator / (const Point& a, const Point& b) {
    return Point(a.x/b.x, a.y/b.y, a.z/b.z);
}

/// <summary>
/// Assignment by division between two points
/// </summary>
/// <param name="a"> The point to be modified </param>
/// <param name="b"> The divisor point </param>
/// <returns> A reference of the point modified </returns>
CICore::Point& CICore::operator /= (Point& a, const Point& b) {
    a.x /= b.x;
    a.y /= b.y;
    a.z /= b.z;

    return a;
}


/// <summary>
/// Sum between a point and a float value
/// </summary>
/// <param name="a"> The point </param>
/// <param name="f"> The float value to be added </param>
/// <returns> The sum between the point and the float value </returns>
CICore::Point CICore::operator + (const Point& a, const float f) {
    return Point(a.x+f, a.y+f, a.z+f);
}

/// <summary>
/// Assignment by addition between a point and a float value
/// </summary>
/// <param name="a"> The point to be modified </param>
/// <param name="b"> The float value to be added </param>
/// <returns> A reference of the point modified </returns>
CICore::Point& CICore::operator += (Point& a, const float f) {
    a.x += f;
    a.y += f;
    a.z += f;

    return a;
}

/// <summary>
/// Difference between a point and a float value
/// </summary>
/// <param name="a"> The point </param>
/// <param name="b"> The float value to be substracted </param>
/// <returns> The difference between the point and the float value </returns>
CICore::Point CICore::operator - (const Point& a, const float f) {
    return Point(a.x-f, a.y-f, a.z-f);
}

/// <summary>
/// Assignment by substraction between a point and a float value
/// </summary>
/// <param name="a"> The point to be modified </param>
/// <param name="b"> The float value to be substracted </param>
/// <returns> A reference of the point modified </returns>
CICore::Point& CICore::operator -= (Point& a, const float f) {
    a.x -= f;
    a.y -= f;
    a.z -= f;

    return a;
}

/// <summary>
/// Product between a point and a float value
/// </summary>
/// <param name="a"> The multiplicand point </param>
/// <param name="b"> The multiplier float value </param>
/// <returns> The product between the and the float value </returns>
CICore::Point CICore::operator * (const Point& a, const float f) {
    return Point(a.x*f, a.y*f, a.z*f);
}

/// <summary>
/// Assignment by multiplication between a point and a float value
/// </summary>
/// <param name="a"> The point to be modified </param>
/// <param name="b"> The multiplier float value </param>
/// <returns> A reference of the point modified </returns>
CICore::Point& CICore::operator *= (Point& a, const float f) {
    a.x *= f;
    a.y *= f;
    a.z *= f;

    return a;
}

/// <summary>
/// Quotient between a point and a float value
/// </summary>
/// <param name="a"> The dividend point </param>
/// <param name="b"> The divisor float value </param>
/// <returns> The quotient between the and the float value </returns>
CICore::Point CICore::operator / (const Point& a, const float f) {
    return Point(a.x/f, a.y/f, a.z/f);
}

/// <summary>
/// Assignment by division between a point and a float value
/// </summary>
/// <param name="a"> The point to be modified </param>
/// <param name="b"> The divisor float value </param>
/// <returns> A reference of the point modified </returns>
CICore::Point& CICore::operator /= (Point& a, const float f) {
    a.x /= f;
    a.y /= f;
    a.z /= f;

    return a;
}
/***************************************************************************************************************
********************************** endregion BASIC POINT's BINARY OPERATIONS **********************************
****************************************************************************************************************/
